/***************************************************************************
*                                                                         *
*   This file is part of the Fotowall project,                            *
*       http://code.google.com/p/fotowall                                 *
*                                                                         *
*   Copyright (C) 2007-2009 by Enrico Ros <enrico.ros@gmail.com>          *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
 * ----------------------------------------------------------------------- *
 *																		   *
 *	Modifications for FotoKinect, Spring 2011 by Gianna Badiali,		   *
 *                                                   Gabriel Fernandez,	   *
 *                                                   Kelsey Tripp, and     *
 *                                                   Sam Swarr             *
 *																		   *
 ***************************************************************************/

#include "PictureContent.h"
#include "ButtonItem.h"
#include "CPixmap.h"
#include "RenderOpts.h"
#include "frames/Frame.h"
#include <QFileInfo>
#include <QGraphicsScene>
#include <QGraphicsSceneDragDropEvent>
#include <QMimeData>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QPainter>
#include <QUrl>
#include <qlabel.h>

PictureContent::PictureContent(QGraphicsScene * scene, QGraphicsItem * parent)
	: AbstractContent(scene, parent, false)
	, m_photo(0)
	, m_opaquePhoto(false)
	, m_progress(0)
	, m_netWidth(0)
	, m_netHeight(0)
	, m_netReply(0)
{

	// allow dropping
	setAcceptDrops(true);
}

PictureContent::~PictureContent()
{
	dropNetworkConnection();
	delete m_photo;
}

bool PictureContent::loadPhoto(const QString & fileName, bool keepRatio, bool setName)
{
	dropNetworkConnection();
	delete m_photo;
	m_cachedPhoto = QPixmap();
	m_opaquePhoto = false;
	m_photo = 0;
	m_fileUrl = QString();
	m_netWidth = 0;
	m_netHeight = 0;

	m_photo = new CPixmap(fileName);
	if (m_photo->isNull()) {
		delete m_photo;
		m_photo = 0;
		return false;
	}

	m_opaquePhoto = !m_photo->hasAlpha();
	m_fileUrl = fileName;
	if (keepRatio)
		resetContentsRatio();
	if (setName) {
		QString string = QFileInfo(fileName).fileName().section('.', 0, 0);
		string = string.mid(0, 10);
	}
	applyPostLoadEffects();

	// notify image change
	emit contentChanged();
	return true;
}

bool PictureContent::loadPhoto(CPixmap *pixmap) {

	delete m_photo;
	m_cachedPhoto = QPixmap();
	m_opaquePhoto = false;
	m_photo = 0;
	m_fileUrl = QString();
	m_netWidth = 0;
	m_netHeight = 0;

	m_photo = pixmap;
	if (m_photo->isNull()) {
		delete m_photo;
		m_photo = 0;
		return false;
	}

	m_opaquePhoto = !m_photo->hasAlpha();
	m_fileUrl = "";
	applyPostLoadEffects();

	// notify image change
	emit contentChanged();
	return true;
}



bool PictureContent::addEffect(const PictureEffect & effect)
{
	if (!m_photo)
		return false;

	if (!m_photo->crop(effect.croppingRect))
		return false;

	if (effect.effect == PictureEffect::Crop) {
		resizeContents(QRect(0,0, (float)m_photo->width(), (float)m_photo->height()));
	}

	m_cachedPhoto = QPixmap();
	update();

	// notify image change
	emit contentChanged();

	return true;
}


bool PictureContent::fromXml(QDomElement & pe)
{
	AbstractContent::fromXml(pe);

	// load picture properties
	QString path = pe.firstChildElement("path").text();

	// build the afterload effects list
	m_afterLoadEffects.clear();
	QDomElement effectsE = pe.firstChildElement("effects");
	for (QDomElement effectE = effectsE.firstChildElement("effect"); effectE.isElement(); effectE = effectE.nextSiblingElement("effect")) {
		PictureEffect fx;
		fx.effect = (PictureEffect::Effect)effectE.attribute("type").toInt();
		fx.param = effectE.attribute("param").toDouble();
		if (fx.effect == PictureEffect::Crop) {
			QString rect = effectE.attribute("croppingRect");
			QStringList coordinates = rect.split(" ");
			if(coordinates.size() >= 3) {
				QRect croppingRect (coordinates.at(0).toInt(), coordinates.at(1).toInt(), coordinates.at(2).toInt(), coordinates.at(3).toInt());
				fx.croppingRect = croppingRect;
			}
		}
		m_afterLoadEffects.append(fx);
	}

	// load Local image
	return loadPhoto(path);
}

void PictureContent::toXml(QDomElement & pe) const
{
	AbstractContent::toXml(pe);
	pe.setTagName("picture");

	// save picture properties
	QDomDocument doc = pe.ownerDocument();
	QDomElement domElement;
	QDomText text;

	// save image url (wether is a local path or remote url)
	domElement = doc.createElement("path");
	pe.appendChild(domElement);
	text = doc.createTextNode(m_fileUrl);
	domElement.appendChild(text);

	// save the effects
	domElement = doc.createElement("effects");
	pe.appendChild(domElement);
	QList<PictureEffect> effectsList = m_afterLoadEffects;
	if (m_photo)
#if QT_VERSION >= 0x040500
		effectsList.append(m_photo->effects());
#else
		foreach(const PictureEffect & effect, m_photo->effects())
		effectsList.append(effect);
#endif
	foreach (const PictureEffect & effect, effectsList) {
		QDomElement effectElement = doc.createElement("effect");
		effectElement.setAttribute("type", effect.effect);
		effectElement.setAttribute("param", effect.param);
		if(effect.effect == PictureEffect::Crop) {
			QString croppingRectStr;
			croppingRectStr = QString::number(effect.croppingRect.x()) + " " + QString::number(effect.croppingRect.y())
				+ " " + QString::number(effect.croppingRect.width()) + " " + QString::number(effect.croppingRect.height());

			effectElement.setAttribute("croppingRect", croppingRectStr );
		}
		domElement.appendChild(effectElement);
	}
}

QPixmap PictureContent::renderContent(const QSize & size, Qt::AspectRatioMode ratio) const
{
	if (m_photo)
		return ratioScaledPixmap(m_photo, size, ratio);
	return QPixmap();
}

int PictureContent::contentHeightForWidth(int width) const
{
	if (m_netWidth > 0 && m_netHeight > 0)
		return (m_netHeight * width) / m_netWidth;
	if (!m_photo || m_photo->width() < 1)
		return -1;
	return (m_photo->height() * width) / m_photo->width();
}

bool PictureContent::contentOpaque() const
{
	return m_opaquePhoto;
}


void PictureContent::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
{
	// paint parent
	AbstractContent::paint(painter, option, widget);

	// draw progress
	if (m_progress > 0.0 && m_progress < 1.0) {
		painter->setPen(Qt::NoPen);
		painter->setBrush(Qt::blue);
		painter->drawPie(QRect(-10, -10, 20, 20), 90 * 16, (int)(-5760.0 * m_progress));
	}

	// skip if no photo
	if (!m_photo)
		return;

	// draw high-resolution photo when exporting png
	QRect targetRect = contentsRect();
	if (RenderOpts::HQRendering) {
		painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
		painter->drawPixmap(targetRect, *m_photo);
		return;
	}

	// draw photo using caching and deferred rescales
	if (beingTransformed()) {
		if (!m_cachedPhoto.isNull())
			painter->drawPixmap(targetRect, m_cachedPhoto);
	} else {
		if (m_cachedPhoto.isNull() || m_cachedPhoto.size() != targetRect.size())
			m_cachedPhoto = m_photo->scaled(targetRect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
		painter->setRenderHints(QPainter::SmoothPixmapTransform);
		painter->drawPixmap(targetRect.topLeft(), m_cachedPhoto);
	}

}

CPixmap PictureContent::getPhoto() const
{
	return *m_photo;
}

void PictureContent::dropNetworkConnection()
{
	if (m_netReply) {
		m_netReply->disconnect(0,0,0);
#if QT_VERSION >= 0x040600
		if (!m_netReply->isFinished())
#endif
			m_netReply->abort();
		m_netReply->deleteLater();
		m_netReply = 0;
	}
	m_progress = 0.0;
}

void PictureContent::applyPostLoadEffects()
{
	foreach (const PictureEffect & effect, m_afterLoadEffects) {
		m_photo->addEffect(effect);
	}
	m_afterLoadEffects.clear();
	update();
}

